package com.yanqu.road.server.gameplayer.module.zhaoshang;

import com.yanqu.road.entity.config.skill.SkillInfo;
import com.yanqu.road.entity.config.zhaoshang.ZsProjectInfo;
import com.yanqu.road.entity.enums.*;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.entity.player.UserPatrons;
import com.yanqu.road.entity.player.UserPatronsSkill;
import com.yanqu.road.entity.rank.UserRank;
import com.yanqu.road.entity.zhaoshang.ZsRobTimes;
import com.yanqu.road.entity.zhaoshang.ZsTopOfRank;
import com.yanqu.road.entity.zhaoshang.ZsUserData;
import com.yanqu.road.entity.zhaoshang.ZsWarReport;
import com.yanqu.road.entity.zhaoshang.enums.eZsReportType;
import com.yanqu.road.logic.bussiness.zhaoshang.ZhaoShangBussiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.logic.pb.ZhaoShangPb;
import com.yanqu.road.pb.common.CommonProto;
import com.yanqu.road.pb.worldmessage.WorldMessageProto;
import com.yanqu.road.pb.zhaoshang.ZhaoShangProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.patrons.PatronsModule;
import com.yanqu.road.server.gameplayer.module.player.AttributeModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.gameplayer.module.player.PlayerModule;
import com.yanqu.road.server.manger.ConfigMgr;
import com.yanqu.road.server.manger.VipMgr;
import com.yanqu.road.server.manger.activity.curio.CurioMgr;
import com.yanqu.road.server.manger.config.SkillMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.player.UserMgr;
import com.yanqu.road.server.manger.zhaoshang.ZsConfigMgr;
import com.yanqu.road.server.manger.zhaoshang.ZsMgr;
import com.yanqu.road.server.pb.WorldMessagePb;
import com.yanqu.road.server.protocol.CrossProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.LocalDateTimeHelper;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 城郊招商
 */
public class ZsModule extends GeneralModule {

    //projectId
    private Map<Long, List<ZsWarReport>> warReportMap;           //战报

    private Map<Integer, ZsUserData>  zsUserDataMap;             //玩家

    private Map<Long, ZsRobTimes> zsRobTimesMap = new ConcurrentHashMap<>();

    public ZsModule(GamePlayer player) {
        super(player);
    }

    @Override
    public boolean loadData() {
        zsUserDataMap = ZhaoShangBussiness.getUserZsData(player.getUserId());
        warReportMap = ZhaoShangBussiness.getZsWarReportMap(player.getUserId());
        zsRobTimesMap = ZhaoShangBussiness.getZsRobTimes(getUserId());
        return true;
    }

    @Override
    public boolean afterLoadData() {
        return true;
    }

    //数据初始化
    private void initData() {
        Date monday = DateHelper.getThisWeekMonday(new Date());
        for(eOccupationType occType : eOccupationType.values()){
            int type = (int)occType.getValue();
            if(!zsUserDataMap.containsKey(type)){
                ZsUserData zsUserData = new ZsUserData();
                zsUserData.setUserId(player.getUserId());
                zsUserData.setType(type);
                zsUserData.setResetTime(monday.getTime());
                zsUserData.setInsertOption();
                zsUserDataMap.put(type, zsUserData);
            }
        }
    }

    @Override
    public void afterLogin() {
        if(SystemOpenMgr.systemOpen(player, eSystemId.ZhaoShang.getValue()) && ZsMgr.isZsSystemOpenTime()){
            initData();
        }
        dataSync();
    }

    private void dataSync() {
        if(!SystemOpenMgr.systemOpen(player, eSystemId.ZhaoShang.getValue())){
            return;
        }
        if(!ZsMgr.isZsSystemOpenTime()){
            return;
        }
        sysZsUserData();
        syncRedDot();
        syncRank();
        //检查同步属于自己的战报
        checkWarReport();
    }

    @Override
    public boolean saveData() {

        for(int type : zsUserDataMap.keySet()){
            ZsUserData zsUserData = zsUserDataMap.get(type);
            if(zsUserData.isInsertOption()){
                ZhaoShangBussiness.addZsUserData(zsUserData);
            }else if(zsUserData.isUpdateOption()) {
                ZhaoShangBussiness.updateZsUserData(zsUserData);
            }
        }

        for(Map.Entry<Long, List<ZsWarReport>> listEntry : warReportMap.entrySet()){
            List<ZsWarReport> reportList = listEntry.getValue();
            int size = reportList.size();
            for(int i = 0; i < size; i++){
                ZsWarReport zsWarReport = reportList.get(i);
                if(zsWarReport.isInsertOption()){
                    ZhaoShangBussiness.addZsWarReport(zsWarReport);
                }else if(zsWarReport.isUpdateOption()){
                    ZhaoShangBussiness.updateZsWarReport(zsWarReport);
                }
            }
        }

        if (zsRobTimesMap != null) {
            for (ZsRobTimes zsRobTimes : new ArrayList<>(zsRobTimesMap.values())) {
                if (zsRobTimes.isInsertOption()) {
                    ZhaoShangBussiness.addZsRobTimes(zsRobTimes);
                } else if (zsRobTimes.isUpdateOption()) {
                    ZhaoShangBussiness.updateZsRobTimes(zsRobTimes);
                }
            }
        }

        return true;
    }

    public Map<Long, List<ZsWarReport>> getWarReportMap() {
        return warReportMap;
    }

    public Map<Integer, ZsUserData> getZsUserDataMap() {
        return zsUserDataMap;
    }

    //项目战报
    public List<ZsWarReport> getZsWarReports(long projectId) {
        List<ZsWarReport> list = warReportMap.get(projectId);
        if(list == null){
            synchronized (warReportMap){
                list = warReportMap.get(projectId);
                if(list == null){
                    list =  new ArrayList<>();
                    warReportMap.put(projectId, list);
                }
            }
        }
        return list;
    }

    //每周重置
    public void resetOneDay(){
        boolean reset = false;
        Date monday = DateHelper.getThisWeekMonday(new Date());
        long time = monday.getTime();
        for(Map.Entry<Integer, ZsUserData> entry : zsUserDataMap.entrySet()) {
            ZsUserData zsUserData = entry.getValue();
            if (time != zsUserData.getResetTime()) {
                zsUserData.setWeekToken(0l);
                zsUserData.setWorShipTimes(0);
                zsUserData.setResetTime(time);
                reset = true;
            }
        }
        if(reset){
            sysZsUserData();
        }
        long now = System.currentTimeMillis();
        if (zsRobTimesMap != null) {
            synchronized (zsRobTimesMap) {
                for (ZsRobTimes zsRobTimes : zsRobTimesMap.values()) {
                    if (!DateHelper.isSameDay(now / 1000, zsRobTimes.getLastResetTime() / 1000)) {
                        zsRobTimes.setRobTimes(0);
                        zsRobTimes.setLastResetTime(now);
                    }
                }
            }
        }
    }

    //领奖(新)
    public void getReward(List<ZsWarReport> zsWarReportList) {
        log.info("ZsModule getReward {}", player.getUserId());
        CurrencyModule currencyModule = player.getModule(CurrencyModule.class);
        UserBaseInfo userBaseInfo = UserMgr.parseUserBaseInfo(player.getUserInfo(), GameServer.getInstance().getServerId());
        int rewardTimes = 0;
        for(ZsWarReport report : zsWarReportList){
            if(!StringUtils.isNullOrEmpty(report.getReward())) {
                Property reward = PropertyHelper.parseStringToProperty(report.getReward());
                if (report.getSeatId() == 0) {
                    currencyModule.addCurrency(reward, eLogMoneyType.ZhaoShang, eLogMoneyType.ZsProjectReward);
                } else {
                    if(report.getType() == eZsReportType.Fail.getIntValue()) {
                        currencyModule.addCurrency(reward, eLogMoneyType.ZhaoShang, eLogMoneyType.ZsProjectSeatExpelReward);
                    }else{
                        currencyModule.addCurrency(reward, eLogMoneyType.ZhaoShang, eLogMoneyType.ZsProjectSeatReward);
                    }
                }
                ZsProjectInfo projectInfo = ZsConfigMgr.getZsProjectInfoMap().get(report.getTemplateId());
                //周收益及排行榜
                ZsUserData zsUserData = zsUserDataMap.get(projectInfo.getType());
                if(zsUserData != null){
                    zsUserData.setWeekToken(zsUserData.getWeekToken() + reward.getCountByGoodsId(getGoodsId(zsUserData.getType())).longValue());
                    UserRank userRank = buildUserRank(zsUserData.getType(), zsUserData.getWeekToken(), player.getUserId(), userBaseInfo);
                    //榜单数据变化
                    ZsMgr.userRankChange(userRank);
                    rewardTimes++;
                }
            }
        }
        if(rewardTimes > 0){
            player.getModule(AttributeModule.class).addAttribute(ePlayerAttrType.ZsTotalRewardTimes, rewardTimes);
            player.notifyListener(eGamePlayerEventType.RechargeZsReward.getValue(), 0);
        }
    }

    private UserRank buildUserRank(int type, long value, long userId, UserBaseInfo userBaseInfo){
        UserRank userRank = new UserRank();
        userRank.setType(type);
        userRank.setValue(BigInteger.valueOf(value));
        userRank.setUserId(userId);
        userRank.setUserBaseInfo(userBaseInfo);
        return userRank;
    }

    //本周收益上传跨服
    private void syncRank() {
        UserBaseInfo userBaseInfo = UserMgr.parseUserBaseInfo(player.getUserInfo(), GameServer.getInstance().getServerId());
        List<UserRank> list = new ArrayList<>();
        for(Map.Entry<Integer, ZsUserData> entry : zsUserDataMap.entrySet()){
            ZsUserData zsUserData = entry.getValue();
            if(zsUserData.getWeekToken() > 0) {
                list.add(buildUserRank(zsUserData.getType(), zsUserData.getWeekToken(), player.getUserId(), userBaseInfo));
            }
        }
        if(list.size() > 0) {
            ZsMgr.userRankChange(list);
        }
    }

    //获取本周代币收益
    public long getUserTokenByType(int rankType) {
        ZsUserData zsUserData = zsUserDataMap.get(rankType);
        if(zsUserData != null){
            return zsUserData.getWeekToken();
        }
        return 0L;
    }

    //膜拜
    public int worShip(int rankType, Property reward) {
        int preWeekId = ZsMgr.getPreWeekId();
        Map<Integer, ZsTopOfRank> zsTopOfRankMap =  ZsMgr.getTopRankMap(preWeekId);
        if(zsTopOfRankMap == null || zsTopOfRankMap.get(rankType) == null){
            return GameErrorCode.E_ZS_PROJECT_TOP_RANK_NOT_FOUND;
        }
        int currentTime  = getCurWorShipTimes(rankType);
        if(currentTime >= ZsMgr.ZS_WEEK_RANK_WORSHIP_TIME_LIMIT){
            return GameErrorCode.E_ZS_PROJECT_TOP_RANK_NOT_WORSHIP_TIMES;
        }
        ZsProjectInfo zsProjectInfo = ZsConfigMgr.getByType(rankType);
        if(zsProjectInfo == null){
            return GameErrorCode.E_ZS_PROJECT_CONFIG_NOT_FOUND;
        }
        //reward.addProperty(PropertyHelper.parseStringToProperty(zsProjectInfo.getWorship()));
        reward.addProperty(calReward(zsProjectInfo.getWorship()));
        player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.ZhaoShang, eLogMoneyType.ZsRankTopWorshipReward);
        addWorShipTimes(rankType);
        sysZsUserData();
        return 0;
    }

    //膜拜奖励计入身份加成
    private Property calReward(String worship) {
        Property baseReward = PropertyHelper.parseStringToProperty(worship);
        int titleAddition = ZsMgr.getTitleAddition(player.getTitleId());
        for (int goodId : baseReward.getGoods().keySet()) {
            BigDecimal baseCount = BigDecimal.valueOf(baseReward.getCountByGoodsId(goodId).longValue());
            long num = baseCount.multiply(BigDecimal.valueOf((double)titleAddition / 1000))
                    .setScale(0, BigDecimal.ROUND_UP).longValue();
            baseReward.setGood(goodId, BigInteger.valueOf(num));
        }
        return baseReward;
    }

    //下发玩家数据
    public void sysZsUserData() {
        if(zsUserDataMap != null && zsUserDataMap.size() == 0){
            return;
        }
        ZhaoShangProto.ZsWeekDataSyncMsg.Builder syncMsg = ZhaoShangProto.ZsWeekDataSyncMsg.newBuilder();

        int preWeekId = ZsMgr.getPreWeekId();
        Map<Integer, ZsTopOfRank> zsTopOfRankMap =  ZsMgr.getTopRankMap(preWeekId);

        //膜拜、榜首信息
        for(Map.Entry<Integer, ZsUserData> entry : zsUserDataMap.entrySet()) {
            ZsUserData zsUserData = entry.getValue();
            ZhaoShangProto.ZsWeekDataTemp.Builder builder = ZhaoShangProto.ZsWeekDataTemp.newBuilder();
            builder.setType(zsUserData.getType());
            builder.setWorShipTimes(zsUserData.getWorShipTimes());
            if(zsTopOfRankMap != null && zsTopOfRankMap.containsKey(entry.getKey())){
                builder.setRankTop(true);
            }
            syncMsg.addDataList(builder);
        }

        player.sendPacket(Protocol.U_ZS_USER_DATA_SYNC, syncMsg);
    }

    //膜拜次数+1
    private void addWorShipTimes(int rankType) {
        ZsUserData zsUserData = zsUserDataMap.get(rankType);
        if(zsUserData != null){
            zsUserData.setWorShipTimes(zsUserData.getWorShipTimes() + 1);
        }
    }

    //获取榜首膜拜次数
    private int getCurWorShipTimes(int rankType){
        ZsUserData zsUserData = zsUserDataMap.get(rankType);
        if(zsUserData != null){
            return zsUserData.getWorShipTimes();
        }
        return ZsMgr.ZS_WEEK_RANK_WORSHIP_TIME_LIMIT;
    }

    //同步玩家信息到跨服2
    public void syncPlayerBaseInfoToCross2(){
        if(!SystemOpenMgr.systemOpen(player, eSystemId.ZhaoShang.getValue())){
            return;
        }
        if(!ZsMgr.isZsSystemOpenTime()){
            return;
        }
        try {
            ZsMgr.uploadUserInfo(player);
        }catch (Exception e){
            log.error(e.getMessage(), e);
        }
    }

    //保证在线，向跨服请求一次战报下发
    private void checkWarReport() {
        ZhaoShangProto.CrossZsPlayerWarReportSyncMsg.Builder syncReqMsg = ZhaoShangProto.CrossZsPlayerWarReportSyncMsg.newBuilder();
        player.sendPacket(CrossProtocol.C2_ZHAO_SHANG_WAR_REPORT_INFO_SYNC, syncReqMsg);
    }

    //跨服下发的战报比对
    public void syncWarReportFromCross(List<ZsWarReport> reportList, boolean verify) {
        long earliestTime = LocalDateTimeHelper.getZeroTimeTimeStamp();
        List<ZsWarReport>  toAddList = new ArrayList<>();   //补偿
        synchronized (warReportMap) {
            for (long projectId : warReportMap.keySet()) {
                List<ZsWarReport> tempList = warReportMap.get(projectId);
                int size = tempList.size();
                for (int i = 0; i < size; i++) {
                    if (earliestTime > tempList.get(i).getSitTime()) {
                        earliestTime = tempList.get(i).getSitTime();
                    }
                }
            }

            for (ZsWarReport report : reportList) {
                ZsWarReport findResult = findWarReport(report.getProjectId(), report.getUserId(), report.getSeatId(), report.getSitTime());
                if (findResult == null) {
                    long time = report.getSitTime();
                    if (time == 0) {
                        time = (long) report.getAddTime() * 1000;
                    }
                    if (report.getType() == eZsReportType.Complete.getIntValue() ||
                            report.getType() == eZsReportType.Fail.getIntValue() || time > earliestTime) {//收官-驱逐战报必增
                        if (verify) {  //通过区服请求同步的检验，进行的补偿
                            report.setSync(true);
                        }
                        report.setInsertOption();
                        toAddList.add(report);
                    }
                } else {
                    findResult.setSync(true);
                }
            }

            for(ZsWarReport report : toAddList){
                getZsWarReports(report.getProjectId()).add(report);
                if(report.getType() != eZsReportType.Complete.getIntValue()) {
                    ZsMgr.addLogZsProjectSeatExpel(report);
                }
            }
        }
    }

    //获取战报
    private ZsWarReport findWarReport(long projectId, long userId, int seatId, long sitTime) {
        if(!warReportMap.containsKey(projectId)){
            return null;
        }
        List<ZsWarReport> zsWarReportList = warReportMap.get(projectId);
        int size = zsWarReportList.size();
        for (int i = 0; i < size; i++) {
            ZsWarReport zsWarReport = zsWarReportList.get(i);
            if (zsWarReport.getSitTime() == sitTime && zsWarReport.getSeatId() == seatId && userId == zsWarReport.getUserId()) {
                return zsWarReport;
            }
        }
        return null;
    }

    //上跨服2取红点(新)
    public void syncRedDot(){
        log.info("ZsModule syncRedDot req {} ", player.getUserId());
        CommonProto.NullValueMsg.Builder reqMsg = CommonProto.NullValueMsg.newBuilder();
        player.sendPacket(CrossProtocol.C2_ZHAO_SHANG_SYNC_RED_DOT, reqMsg);
    }

    //下发红点，服务端负责项目收官、被驱逐情况（战报、奖励）
    public void syncRedDot2(){
        boolean sendRedHot = false;
        for(long projectId : warReportMap.keySet()){
            List<ZsWarReport> tempList = warReportMap.get(projectId);
            int size = tempList.size();
            for(int i=0; i < size; i++){
                ZsWarReport zsWarReport = tempList.get(i);
                if(!zsWarReport.isSendReward() && zsWarReport.getType() != eZsReportType.Win.getIntValue()){
                    sendRedHot = true;
                    break;
                }
            }
            if(sendRedHot){
                break;
            }
        }
        if(sendRedHot){
            WorldMessageProto.RedHotNotifyMsg.Builder redHotMsg = WorldMessagePb.parseRedHotNotifyMsg(eRedHotNotifyType.ZsWarReport.getValue(), 1, null);
            player.sendPacket(Protocol.U_RED_HOT_NOTIFY, redHotMsg);
        }
    }

    //获取代币道具id
    private int getGoodsId(int type) {
        int goodsId = 0;
        if(eOccupationType.Scholar.getValue() == type){
            goodsId = eItemId.ZHAO_SHANG_SCHOLAR_TOKEN.getValue();
        }else if(eOccupationType.Farmer.getValue() == type){
            goodsId = eItemId.ZHAO_SHANG_FARMER_TOKEN.getValue();
        }else if(eOccupationType.Craftsman.getValue() == type){
            goodsId = eItemId.ZHAO_SHANG_CRAFTS_TOKEN.getValue();
        }else if(eOccupationType.Businessman.getValue() == type){
            goodsId = eItemId.ZHAO_SHANG_BUSINESS_TOKEN.getValue();
        }else if(eOccupationType.Knight.getValue() == type){
            goodsId = eItemId.ZHAO_SHANG_KNIGHT_TOKEN.getValue();
        }
        return goodsId;
    }

    //系统解锁
    public void initSystem() {
        if(!ZsMgr.isZsSystemOpenTime()){
            return;
        }
        //解锁刷新门客技能数据
        player.getModule(PatronsModule.class).flushPatronsSkill();

        initData();
        sysZsUserData();
    }

    //分组变更造成的系统开启
    public void crossServerGroupReload(){
        if(SystemOpenMgr.systemOpen(player, eSystemId.ZhaoShang.getValue()) && ZsMgr.isZsSystemOpenTime()){
            //解锁刷新门客技能数据
            player.getModule(PatronsModule.class).flushPatronsSkill();

            initData();
            sysZsUserData();
        }
    }

    /**
     * 是否可以解锁技能
     * @return
     */
    public boolean isZsSystemOpen() {
        if(!SystemOpenMgr.systemOpen(player, eSystemId.ZhaoShang.getValue())){
            return false;
        }
        if(!ZsMgr.isZsSystemOpenTime()){
            return false;
        }
        return true;
    }

    public int getZsRobNum() {
        int addFreeTimes = 0;
        List<UserPatrons> userPatronsList = player.getModule(PatronsModule.class).getUserPatronsList();
        for (UserPatrons patrons : userPatronsList) {
            for (UserPatronsSkill skill : patrons.getSkillList()) {
                if (skill.getType() != ePatronsSkillType.Talent.getValue()) {
                    continue;
                }
                SkillInfo skillInfo = SkillMgr.getSkillInfo(skill.getSkillId());
                if (skillInfo.getType() == eSkillType.ZsSeatAddition.getValue()) {
                    addFreeTimes += SkillMgr.getSkillAddition(skillInfo, skill.getSkillLv());
                }
            }
        }
        return addFreeTimes + GameConfig.ZS_PROJECT_ROB_NUM_LIMIT;
    }

    public int getLimitMultiple() {
        //按照vip等级获取项目开启倍数
        List<Integer> multipleList = ConfigMgr.getZsProjectOpenMultiple();
        int limitMultiple = multipleList.get(0);
        int vipLevel = VipMgr.getVipLv(player.getModule(PlayerModule.class).getUserInfo().getVipExp());
        if(vipLevel > 0 && vipLevel < multipleList.size()){
            limitMultiple = multipleList.get(vipLevel);
        }else if(vipLevel >= multipleList.size()){
            limitMultiple = multipleList.get(multipleList.size() - 1);
        }
        return limitMultiple;
    }

    public int getZsOpenNum() {
        int addFreeTimes = 0;
        List<UserPatrons> userPatronsList = player.getModule(PatronsModule.class).getUserPatronsList();
        for (UserPatrons patrons : userPatronsList) {
            for (UserPatronsSkill skill : patrons.getSkillList()) {
                SkillInfo skillInfo = SkillMgr.getSkillInfo(skill.getSkillId());
                if (skillInfo.getType() == eSkillType.ZsOpenAddition.getValue()) {
                    addFreeTimes += SkillMgr.getSkillAddition(skillInfo, skill.getSkillLv());
                }
            }
        }
        int skillAdd = (int)CurioMgr.getSkillAdditionBySkillType(eSkillType.CurioZSOpenTimeSkill.getValue(), player, 0);
        return addFreeTimes + GameConfig.ZS_PROJECT_OPEN_NUM_LIMIT + skillAdd;
    }

    public void addRobTimes(long robUserId) {
        synchronized (zsRobTimesMap) {
            ZsRobTimes zsRobTimes = zsRobTimesMap.get(robUserId);
            if (zsRobTimes == null) {
                zsRobTimes = new ZsRobTimes();
                zsRobTimes.setUserId(getUserId());
                zsRobTimes.setRobUserId(robUserId);
                zsRobTimes.setLastResetTime(System.currentTimeMillis());
                zsRobTimes.setInsertOption();
                zsRobTimesMap.put(robUserId, zsRobTimes);
            }
            zsRobTimes.setRobTimes(zsRobTimes.getRobTimes() + 1);
        }
    }

    public boolean isOverRobTimes(long robUserId) {
        ZsRobTimes zsRobTimes = zsRobTimesMap.get(robUserId);
        if (zsRobTimes == null) {
            return false;
        }
        return zsRobTimes.getRobTimes() >= GameConfig.ZS_DAILY_ROB_SAME_PLAYER_TIMES;
    }

}
